
/*
防拆报警
*/

#include "BSP_Alarm.h"
#include "Timer.h"
#include "Buzzer.h"
#include "Door.h"
#include "Alarm.h"
#include "Env.h"

#define Signal_Check(sig, type)		(((sig) & (1u << (type))) != 0)
#define Signal_Clear(sig, type)		do{(sig) &= ~ (1u << (type));}while(0)

static Timer_T alarmTimer;
static int8_t alarmState;
static uint32_t alarmCount;
static int8_t alarmPreState;

static uint8_t alarmSignal;
static uint8_t alarmPreSig;
static uint16_t alarmMagCount;
static uint8_t alarmTirged;
static uint8_t alarmSigSuspend;
static SigType_T alarmLast;

static void Alarm_Dummy(int e, SigType_T sig){}
static void (*alarmNotify)(int e, SigType_T sig) = Alarm_Dummy;

/*--------------------软触发报警--------------------------------*/
void Alarm_Trig(uint8_t sig){
	alarmTirged |= envProp.alarmEanble & Signal_Mask(sig);
}


void Alarm_Cancle(uint8_t sig){
	alarmTirged &= ~ Signal_Mask(sig);
}

int Alarm_Check(uint8_t sig){
	return (alarmTirged & Signal_Mask(sig)) != 0;
}
/*----------------------------------------------------*/
/*
恢复报警
*/
void Alarm_Active(void){
	__disable_irq();
	alarmState = 0;	
	alarmPreState = 0;
	Timer_Restart(&alarmTimer);
	__enable_irq();
}

/*
取消报警
*/
void Alarm_Deactive(void){
	__disable_irq();
	Timer_Stop(&alarmTimer);
	Buzzer_Off();
	BSP_Alarm_Out(0);
	alarmState = -3;
	alarmPreState = -3;
	__enable_irq();
}


/*
配置报警信号
*/

void Alarm_Config(uint8_t config){
	if(envProp.alarmEanble != config){
		Env_Set(&envProp.alarmEanble, &config, sizeof(config));
	}
	if(envProp.alarmEanble){
		Alarm_Active();
	}
	else{
		Alarm_Deactive();
	}
}

/*
使能报警
*/
void Alarm_Enable(uint8_t enable){
	uint8_t config = envProp.alarmEanble | enable;
	Alarm_Config(config);
}

/*
禁止报警
*/
void Alarm_Disable(uint8_t disable){
	uint8_t config = envProp.alarmEanble & ~disable;
	Alarm_Config(config);
}


/*
暂停报警蜂鸣器
*/
void Alarm_PauseBuzzer(void){
	__disable_irq();
	Buzzer_Off();
	if(alarmState != 1){
		alarmPreState = alarmState;
	}
	alarmState = 1;
	alarmCount = 0;
	__enable_irq();
}

/*
暂停报警10分钟
*/
void Alarm_Suspend(void){
	__disable_irq();
	Buzzer_Off();
	BSP_Alarm_Out(0);
	alarmState = -2;
	alarmPreState = -2;
	alarmCount = 0;
	alarmSigSuspend = alarmPreSig;
	__enable_irq();
}


static void AlramCallback(void){	
	uint8_t sig = BSP_Alarm_Signal();
	int alarmNotice = 0;
	
	sig |= alarmTirged;
	//消防报警不能屏蔽
	sig &= envProp.alarmEanble;	

	
	switch(alarmState){
	case 0:{
		alarmPreSig = sig;
		if(sig){
			//有报警信号，跳转到状态2防抖
			alarmState = 2;
			alarmCount = 0;
		}
		else{
			alarmNotice = -1;
		}
	}
	break;
	
	case 2:{
		if(sig == alarmPreSig){
			alarmSignal = sig;
			//门磁报警、错按报警不保存，报警状态实时更新
			//其余报警，只有开门后才能消除报警。
			Signal_Clear(alarmSignal, SigType_Mag);
			Signal_Clear(alarmSignal, SigType_Key);
			alarmState = 3;
			alarmCount = 0;
			alarmMagCount = 0;
		}
		else{
			alarmState = 0;
		}
	}
	break;

	case 3:{
		if(alarmPreSig != sig){
			//报警信号发生变化，跳转到状态4防抖
			alarmPreSig = sig;
			alarmState = 4;
			break;
		}
		
		uint8_t ss = (alarmSignal | sig);
		
//		if(Signal_Check(ss, SigType_Fire)){
//			//消防报警
//			alarmLast = SigType_Fire;
//			alarmNotice = 1;
//			Door_Unlock(envProp.unlockTime);
//		}
//		
//		if(Signal_Check(ss, SigType_Tamper)){
//			//防拆报警（蜂鸣）
//			alarmLast = SigType_Tamper;
//			alarmNotice = 1;
//			Buzzer_On();
//		}
		
		if(Signal_Check(ss, SigType_Mag)){
			if(alarmMagCount < (10 * envProp.devParams.magWarningTimeout)){
				++alarmMagCount;
			}
			//门磁报警延时，在延时时间内报警信号消除，则不触发报警
			if(alarmMagCount >= (10 * envProp.devParams.magWarningTimeout)){
				//门磁报警
				alarmLast = SigType_Mag;
				alarmNotice = 1;
				Buzzer_On();
			}
		}
		else{
			alarmMagCount = 0;
		}
		
		if(Signal_Check(ss, SigType_Key)){
			alarmLast = SigType_Key;
			alarmNotice = 1;
		}
		
		if(ss == 0){
			//报警解除
			Buzzer_Off();
			alarmNotice = -1;
			alarmState = 0;
		}
	}
	break;
	
	case 4:{
		if(alarmPreSig == sig){
			alarmSignal |= sig;
			//门磁报警、错按报警不保存，报警状态实时更新
			//其余报警，只有开门后才能消除报警。
			Signal_Clear(alarmSignal, SigType_Mag);
			Signal_Clear(alarmSignal, SigType_Key);
			alarmState = 3;
		}
		else{
			alarmPreSig = sig;
		}
	}
	break;
	
	case 1:{
		//暂停报警
		++alarmCount;
		if(alarmCount > 10){
			alarmCount = 0;
			alarmState = alarmPreState;
		}
	}
	break;
	
	case -2:{

		alarmSigSuspend &= sig;
		
		if(alarmSigSuspend == 0){
			//报警已经消除，恢复检查报警。
			alarmState = 0;
			alarmCount = 0;
		}
		else{

			++alarmCount;
			if(alarmCount > (10 * 60 * 10)){
				//挂起10分钟后重新报警
				alarmCount = 0;
				alarmState = 0;
				alarmSigSuspend = 0;
			}
			else
			if(sig & ~alarmSigSuspend){
				//有新的报警
				alarmState = 4;
			}
		}
	}
	break;

	}
	if(alarmNotice){
		if(alarmNotice > 0){
			BSP_Alarm_Out(1);
		}
		else{
			BSP_Alarm_Out(0);
		}
		alarmNotify(alarmNotice, alarmLast);
	}
}

void Alarm_RegisterNotify(void(*notify)(int e, SigType_T sig)){
	alarmNotify = notify;
}

void Alarm_UnregisterNotify(void){
	alarmNotify = Alarm_Dummy;
}

/*
初始化报警
*/
void Alarm_Init(void){
	Timer_Setup(&alarmTimer, 10, 1, 0, AlramCallback);
}

/*
获取报警状态
*/
int8_t Alarm_State(void){
	return BSP_Alarm_State();
}



